/**
 * 
 */
package com.geezdata.cps.base.aop;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Map;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.geezdata.cps.base.annotation.FailedRetry;
import com.geezdata.cps.base.exceptions.BusinessException;
import com.geezdata.cps.base.utils.HttpClientUtil;
import com.google.common.collect.Maps;

/**
 * @author sszheng
 * @date 创建时间：2017年10月13日 下午4:30:45
 *
 */
@Aspect
@Order(6)
@Component
public class FailedRetryAspect {
	private static final Logger logger = LoggerFactory.getLogger(FailedRetryAspect.class);
	
	@Around("@annotation(com.geezdata.cps.base.annotation.FailedRetry)")
	public Object failedRetry(ProceedingJoinPoint pjp) throws Throwable {
		Object res = null;
		try {
			res = pjp.proceed();
		} catch(BusinessException e) {
			saveFailedTask(pjp, e);
			throw e;
		}
		
		return res;
	}

	private void saveFailedTask(ProceedingJoinPoint pjp, BusinessException e) {
		String message = JSON.toJSONString(e.getParams());
		Method method = getMethod(pjp);
		FailedRetry anno = method.getAnnotation(FailedRetry.class);
		String failedTaskType = anno.failedTaskType();
		
		Map<String, Object> failedTask = Maps.newHashMap();
		failedTask.put("url", e.getUrl());
		failedTask.put("message", message);
		failedTask.put("failed_task_type", failedTaskType);
		failedTask.put("status", 0);
		
		Map<String, Object> request = Maps.newHashMap();
		request.put("failed_task", failedTask);
		try {
			HttpClientUtil.post(e.getFailedTaskUrl(), request );
		} catch (IOException e1) {
			logger.error(e1.getMessage());
		}
	}

	private Method getMethod(ProceedingJoinPoint pjp)  {
		Signature sig = pjp.getSignature();
        MethodSignature msig = null;
        if (!(sig instanceof MethodSignature)) {
            throw new IllegalArgumentException("该注解只能用于方法");
        }
        msig = (MethodSignature) sig;
        Object target = pjp.getTarget();
        Method currentMethod = null;
		try {
			currentMethod = target.getClass().getMethod(msig.getName(), msig.getParameterTypes());
		} catch (NoSuchMethodException | SecurityException e) {
			logger.error(e.getMessage(), e);
		}
        return currentMethod;
	}
}
